package com.zm.openapi.filters.init;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.ImmutableMap;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.rewrite.ModifyRequestBodyGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.rewrite.RewriteFunction;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @description: 修改 系统 Http 请求body的过滤器工厂
 * @module: com.zm.apigateway.Filters
 * @author: songxiongli
 * @date: 2020-03-13 12:30
 **/
@Slf4j
@Component
public abstract class AbstrModifyHttpBodyGatewayFilterFactory extends ModifyRequestBodyGatewayFilterFactory {

    public AbstrModifyHttpBodyGatewayFilterFactory() {
        super();
    }

    @Resource
    private JsonHttpBodySerializer jsonHttpBodySerializer;
    @Resource
    private FormdataHttpBodySerializer formdataHttpBodySerializer;

    private ImmutableMap<String, IHttpBodySerializer> HTTP_BODY_SERIALIZER_IMMUTABLE_MAP = null;

    @PostConstruct
    public void init() {
        HTTP_BODY_SERIALIZER_IMMUTABLE_MAP =
                ImmutableMap.<String, IHttpBodySerializer>builder().put(MediaType.APPLICATION_JSON_VALUE.toLowerCase(), jsonHttpBodySerializer)
                        .put(MediaType.APPLICATION_FORM_URLENCODED_VALUE.toLowerCase(), formdataHttpBodySerializer)
                        .put(MediaType.MULTIPART_FORM_DATA_VALUE.toLowerCase(), formdataHttpBodySerializer)
                        .put(MediaType.APPLICATION_JSON_UTF8_VALUE.toLowerCase(), jsonHttpBodySerializer)
                        .put(MediaType.TEXT_PLAIN_VALUE.toLowerCase(), jsonHttpBodySerializer)
                        .build();
    }

    @Override
    public GatewayFilter apply(ModifyRequestBodyGatewayFilterFactory.Config config) {
        config.setRewriteFunction(String.class, String.class, getRewriteFunction(getHttpBodyModifier()));

        return super.apply(config);
    }

    /**
     * 自定义修改http body内容
     *
     * @param httpBodyModifier
     * @return
     */
    private RewriteFunction<String, String> getRewriteFunction(HttpBodyModifier httpBodyModifier) {
        return (exch, body) -> {
            ServerWebExchange exchange = (ServerWebExchange) exch;

            String contentyType = exchange.getRequest() != null ? exchange.getRequest().getHeaders().getContentType().toString()
                    : exchange.getResponse().getHeaders().getContentType().toString();
            if (StringUtils.isBlank(contentyType)) {
                contentyType = MediaType.APPLICATION_JSON_VALUE;
            }
            contentyType = contentyType.toLowerCase();

            Map preBody = HTTP_BODY_SERIALIZER_IMMUTABLE_MAP.get(contentyType).serialize(body);
            if (preBody == null) {
                preBody = new LinkedHashMap();
            }

            Map modifiedBody = httpBodyModifier.modify(exchange, preBody);
            if (MapUtils.isEmpty(modifiedBody)) {
                log.info("修改后的http body为空,requestpath={},preBody={}", JSON.toJSONString(exchange.getRequest().getPath()), preBody);
            }

            return Mono.just(HTTP_BODY_SERIALIZER_IMMUTABLE_MAP.get(contentyType).deserialize(modifiedBody));
        };
    }

    protected abstract HttpBodyModifier getHttpBodyModifier();
}
